﻿
namespace Patterns4Net.PatternEnforcer.Core.ClassCheckers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Mono.Cecil;
    using Patterns4Net.Core.CecilExtensions;

    /// <summary>
    /// Checks that all methods that could be overridden are really overridden.
    /// </summary>
    public class EverythingIsOverridden : IChecker<TypeDefinition>
    {
        private readonly bool checkSystemObjectMethods;

        public EverythingIsOverridden(bool checkSystemObjectMethods)
        {
            this.checkSystemObjectMethods = checkSystemObjectMethods;
        }

        public CheckerResult Check(TypeDefinition type)
        {
            var result = new CheckerResultBuilder();

            var methodsToBeOverriden = new List<MethodReference>(type.GetOverrideableMethods());

            if (this.checkSystemObjectMethods == false)
            {
                methodsToBeOverriden.RemoveAll(m => m.DeclaringType.IsEqual(typeof(object)));
            }

            if (methodsToBeOverriden.Count() == 0)
            {
                return new CheckerResult(0, CheckerError.EmptyArray);
            }

            result.AddCheckedRules(methodsToBeOverriden.Count());

            var notOverriden = methodsToBeOverriden.Where(m => type.Overrides(m) == false);
            foreach (var method in notOverriden)
            {
                result.Add(ErrorMessages.TypeDoesNotOverrideMethod, type.Name, method.Name);                
            }

            return result.Build();
        }
    }
}
